package com.tencent.sr.iris.activity.service.event.activity;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.tencent.sr.iris.activity.dependency.user.UserLabelDependency;
import com.tencent.sr.iris.activity.domain.event.dto.ActivityCheckResultDTO;
import com.tencent.sr.iris.activity.domain.event.dto.ActivityDTO;
import com.tencent.sr.iris.activity.domain.event.dto.ActivityTaskDTO;
import com.tencent.sr.iris.activity.interfaces.enums.ActivityEventTypeEnum;
import com.tencent.sr.iris.activity.interfaces.event.dto.ActivityEventDTO;
import com.tencent.sr.iris.activity.service.activity.ActivityCommonService;
import com.tencent.sr.iris.activity.service.activity.IrisUserTaskRecordService;
import com.tencent.sr.iris.activity.service.config.ActivityConfig;
import com.tencent.sr.iris.activity.service.event.task.IrisTaskExecutor;
import com.tencent.sr.iris.activity.service.event.util.ActivityCommonUtilService;
import com.tencent.sr.iris.user.core.service.interfaces.enums.SpecialInviteTypeEnum;
import com.tencent.sr.iris.user.core.service.interfaces.enums.StaffFromTypeEnum;
import com.tencent.sr.iris.user.core.service.interfaces.enums.TutorChannelSettingEnum;
import com.tencent.sr.iris.user.core.service.interfaces.enums.UserLevelEnum;
import com.tencent.sr.iris.user.core.service.interfaces.request.tag.SpecialLeaderTagMqRequest;
import com.tencent.sr.iris.user.core.service.interfaces.response.activity.SpecialInviteResponse;
import com.tencent.sr.iris.user.core.service.interfaces.response.user.IrisQueryUsersInTagsResponse;
import com.tencent.sr.rmall.common.exception.retail.TRetailErrorException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * @author xiaojun
 * 注：当前活动处理器的对象名称是 活动类型ActivityEventTypeEnum的code
 */
@Slf4j
@Component
public class SpecialIrisInviteGiftActivityExecutor extends AbstractIrisActivityExecutor {

    @Resource
    public ActivityConfig activityConfig;

    @Resource
    private IrisUserTaskRecordService userTaskRecordService;

    @Resource
    private ActivityCommonService activityCommonService;

    @Resource
    private ActivityCommonUtilService activityCommonUtilService;

    @Resource
    private UserLabelDependency userLabelDependency;

    @Override
    protected void process(ActivityEventDTO msg, ActivityDTO activity, List<String> eventHandingInfoList) {

        //特邀打标事件
        if (ActivityEventTypeEnum.SPECIAL_INVITE.getCode().equals(msg.getEventType())) {
            String eventInfo = msg.getEventInfo();
            SpecialLeaderTagMqRequest specialLeaderTagMqRequest = JSON.parseObject(eventInfo,
                    SpecialLeaderTagMqRequest.class);
            //如果是取消特邀标事件，删除用户进行中的任务，否则不处理
            if (SpecialInviteTypeEnum.DELETE.getCode().equals(specialLeaderTagMqRequest.getType())) {

                int i = userTaskRecordService.deleteInProgressTaskRecord(msg.getUid(), activity.getBizId(),
                        null);
                eventHandingInfoList.add("取消特邀标事件，删除进行中的任务记录,result:" + i + "条");
                activityRecordService.handleInProgressActivityRecord(msg.getUid(), activity.getBizId());
                return;
            }
        }

        //其它事件
        //1.活动规则校验
        ActivityCheckResultDTO activityFlag = doActivityCheck(activity, msg);
        if (!activityFlag.isSatisfy()) {
            log.info("不满足活动规则,activityId={},errorMsg:{}, msg={}", activity.getBizId(), activityFlag.getErrorMsg(),
                    JSONObject.toJSONString(msg));
            eventHandingInfoList.add("不满足活动规则,errorMsg=" + activityFlag.getErrorMsg());
            return;
        }
        //2.活动准入规则校验，不满足则删除进行中的任务记录
        ActivityCheckResultDTO accessConditionCheckResult = doAccessConditionCheck(activity, msg);
        if (!accessConditionCheckResult.isSatisfy()) {
            log.info("不满足活动准入规则,activityId={},errorMsg:{}, msg={}", activity.getBizId(),
                    accessConditionCheckResult.getErrorMsg(),
                    JSONObject.toJSONString(msg));
            eventHandingInfoList.add("不满足活动准入规则,errorMsg=" + accessConditionCheckResult.getErrorMsg());
            //如果不满足活动任务门槛，删除已存在的进行中任务记录
            int i = userTaskRecordService.deleteInProgressTaskRecord(msg.getUid(), activity.getBizId(),
                    null);
            eventHandingInfoList.add("不满足活动准入规则，删除进行中的任务记录,result:" + i + "条");
            activityRecordService.handleInProgressActivityRecord(msg.getUid(), activity.getBizId());
            return;
        }

        activity.getActivityTaskDTOS().forEach(t -> {
            //获取任务执行器
            IrisTaskExecutor taskExecutor = getTaskExecutor(msg, activity, t);
            taskExecutor.execute(msg, activity, t, null);
        });

        activityRecordService.addOrUpdateActivityRecord(msg.getUid(), msg.getEventTime(), activity.getBizId(),
                activity.getPeriodType(), activity.getPeriod());
    }


    @Override
    protected void after(ActivityEventDTO eventDTO, ActivityDTO act) {

    }

    @Override
    protected List<ActivityTaskDTO> getTask(ActivityEventDTO eventDTO, ActivityDTO act) {
        return null;
    }


    @Override
    protected void check(ActivityEventDTO msg, ActivityDTO activity) {

    }

    @Override
    public ActivityCheckResultDTO doActivityCheck(ActivityDTO activity, ActivityEventDTO msg) {
        log.info("开始校验是否有资格进入特邀邀请有礼活动,ActivityEventDTO:{}", JSON.toJSONString(msg));
        String uid = msg.getUid();
        Long becomeTraineeTime = activityCommonService.queryTraineeTime(uid);
        if (becomeTraineeTime == null) {
            log.info("用户成为见习会员的时间为空");
            return ActivityCheckResultDTO.builder().satisfy(false).errorMsg("用户成为见习会员的时间为空").build();
        }
        //判断是否在活动有效期内
        if (BooleanUtils.isFalse(activityCommonUtilService.checkActivityTime(activity, becomeTraineeTime))) {
            log.info("成为见习会员时间不在活动范围内");
            return ActivityCheckResultDTO.builder().satisfy(false).errorMsg("成为见习会员时间超出活动时间范围").build();
        }
        //事件是否是成为见习会员30天内
        if (BooleanUtils.isFalse(activityCommonUtilService.checkTraineeTime(msg, becomeTraineeTime))) {
            log.info("见习会员30天内校验不通过");
            return ActivityCheckResultDTO.builder().satisfy(false)
                    .errorMsg("不满足注册见习会员30内时间条件或者非活动开始后成为见习会员,无法参与特邀邀请有礼活动")
                    .build();
        }

        // 是否在设置结束时间之后，需求id：ID114913012
        long currentTimeMillis = System.currentTimeMillis();
        long specialInviteEndTimeTimestamp = activityCommonUtilService.getSpecialInviteEndTimeTimestamp(uid);
        if (currentTimeMillis > specialInviteEndTimeTimestamp) {
            log.info("在特邀结束时间后");
            return ActivityCheckResultDTO.builder().satisfy(false).errorMsg("不满足特邀活动结束时间内").build();
        }

        return ActivityCheckResultDTO.builder().satisfy(true).build();
    }


    /**
     * 活动准入条件判断，不符合条件会删除用户在活动下的进行中的任务记录
     *
     * @param activity
     * @param msg
     * @return
     */
    @Override
    public ActivityCheckResultDTO doAccessConditionCheck(ActivityDTO activity, ActivityEventDTO msg) {

        String uid = msg.getUid();
        String pid = msg.getPid();
        String idempotent = msg.getIdempotent();

        IrisQueryUsersInTagsResponse userTags = activityCommonUtilService.queryUserTags(uid);
        if (Objects.isNull(userTags) || CollectionUtils.isEmpty(userTags.getTagIdList())) {
            throw new TRetailErrorException("查询用户标签信息失败");
        }
        if (!CollectionUtil.containsAny(userTags.getTagIdList(), Arrays.asList(TutorChannelSettingEnum.GROUP.getValue(),
                TutorChannelSettingEnum.COMMON_TUTOR.getValue()))) {
            log.info("上级【{}】的下级【{}】不符合用户升级场景值：团长、公共导师", pid, uid);
            return ActivityCheckResultDTO.builder().satisfy(false).errorMsg("下级不符合用户升级场景值：团长、公共导师").build();
        }

        Long becomeTraineeTime = activityCommonService.queryTraineeTime(uid);
        if (becomeTraineeTime == null) {
            log.info("用户成为见习会员的时间为空");
            return ActivityCheckResultDTO.builder().satisfy(false).errorMsg("用户成为见习会员的时间为空").build();
        }
        LocalDate traineeLocalDate = Instant.ofEpochMilli(becomeTraineeTime).atZone(ZoneOffset.ofHours(+8))
                .toLocalDate();

        //校验下级
        if (activityCommonUtilService.checkSpecialInvite(uid)) {
            log.info("下级不是特邀,uid:{},pid:{},idempotent:{}", uid, pid, msg.getIdempotent());
            return ActivityCheckResultDTO.builder().satisfy(false).errorMsg("下级不是特邀会员").build();
        }
        //校验下级是否 高级/超级
        if (!activityCommonUtilService.isUserLevelIn(uid,
                Lists.newArrayList(UserLevelEnum.SENIOR.getValue(), UserLevelEnum.SUPER.getValue()))) {
            log.info("下级不是高级/超级,uid:{},pid:{},idempotent:{}", uid, pid, msg.getIdempotent());
            return ActivityCheckResultDTO.builder().satisfy(false).errorMsg("下级不是高级/超级").build();
        }
        //校验下级是否 外部未签约/外部已签约
        if (!activityCommonUtilService.isStaffFromTypeIn(uid,
                Lists.newArrayList(StaffFromTypeEnum.OUTER_NON_SIGN, StaffFromTypeEnum.OUTER_SIGN))) {
            log.info("下级不是外部未签约/外部已签约,uid:{},pid:{},idempotent:{}", uid, pid, msg.getIdempotent());
            return ActivityCheckResultDTO.builder().satisfy(false).errorMsg("下级不是外部未签约/外部已签约").build();
        }

        //校验成为见习会员时间和成为高级/超级时间
        LocalDate startDate = getStrictStandardStartDate(uid);

        if (traineeLocalDate.isBefore(startDate)) {
            log.info("用户成为见习会员的时间在" + startDate + "之前,uid:{},pid:{},idempotent:{}", uid, pid, idempotent);
            return ActivityCheckResultDTO.builder().satisfy(false).errorMsg("用户成为见习会员的时间在" + startDate + "之前").build();
        }
        SpecialInviteResponse specialInviteResponse = activityCommonUtilService.querySpecialInvite(uid);
        Long specialInviteTimeStamp = specialInviteResponse.getTimeStamp();
        LocalDate specialInviteLocalDate = Instant.ofEpochMilli(specialInviteTimeStamp).atZone(ZoneOffset.ofHours(+8))
                .toLocalDate();
        if (traineeLocalDate.isAfter(specialInviteLocalDate)) {
            log.info("用户成为见习会员的时间在成为特邀会员时间之后,uid:{},pid:{},idempotent:{}", uid, pid, idempotent);
            return ActivityCheckResultDTO.builder().satisfy(false).errorMsg("用户成为见习会员的时间在成为特邀会员时间之后").build();
        }
        LocalDate traineeLocalDatePlus29 = traineeLocalDate.plusDays(29);
        if (traineeLocalDatePlus29.isBefore(specialInviteLocalDate)) {
            log.info("成为特邀会员时间在用户成为见习会员的时间+29天在之后,uid:{},pid:{},idempotent:{}", uid, pid, idempotent);
            return ActivityCheckResultDTO.builder().satisfy(false).errorMsg("成为特邀会员时间在用户成为见习会员的时间+29天在之后").build();
        }

        String userLevelId = activityCommonUtilService.queryUserLevelIdUseCache(uid);
        //查询当前用户成为高级的时间
        Long timeStamp = activityCommonUtilService.queryUserMemberTimeStampUseCache(uid, userLevelId);

        ///查询当前用户成为当前等级的时间
        LocalDate userMemberDate = Instant.ofEpochMilli(timeStamp).atZone(ZoneId.systemDefault()).toLocalDate();
        if (traineeLocalDate.isAfter(userMemberDate)) {
            log.info("成为见习会员时间在用户成为高级/超级会员的时间之后,uid:{},pid:{},idempotent:{}", uid, pid, idempotent);
            return ActivityCheckResultDTO.builder().satisfy(false).errorMsg("成为见习会员时间在用户成为高级会员的时间之后").build();
        }

        //校验上级
        ActivityCheckResultDTO activityCheckResultDTO = doPidAccessConditionCheck(pid, uid, idempotent);
        if (activityCheckResultDTO != null) {
            return activityCheckResultDTO;
        }

        return ActivityCheckResultDTO.builder().satisfy(true).build();
    }

    /**
     * 上级准入校验
     *
     * @param pid
     * @param uid
     * @param idempotent
     * @return
     */
    public ActivityCheckResultDTO doPidAccessConditionCheck(String pid, String uid, String idempotent) {
        if (activityCommonUtilService.checkSpecialInvite(pid)) {
            log.info("上级不是特邀,uid:{},pid:{},idempotent:{}", uid, pid, idempotent);
            return ActivityCheckResultDTO.builder().satisfy(false).errorMsg("上级不是特邀会员").build();
        }
        //校验上级是否 高级/超级
        if (!activityCommonUtilService.isUserLevelIn(pid,
                Lists.newArrayList(UserLevelEnum.SENIOR.getValue(), UserLevelEnum.SUPER.getValue()))) {
            log.info("上级不是高级/超级,uid:{},pid:{},idempotent:{}", uid, pid, idempotent);
            return ActivityCheckResultDTO.builder().satisfy(false).errorMsg("上级不是高级/超级").build();
        }
        //校验上级是否 外部未签约/外部已签约
        if (!activityCommonUtilService.isStaffFromTypeIn(pid,
                Lists.newArrayList(StaffFromTypeEnum.OUTER_NON_SIGN, StaffFromTypeEnum.OUTER_SIGN))) {
            log.info("上级不是外部未签约/外部已签约,uid:{},pid:{},idempotent:{}", uid, pid, idempotent);
            return ActivityCheckResultDTO.builder().satisfy(false).errorMsg("上级不是外部未签约/外部已签约").build();
        }

        return null;
    }

    /**
     * 获取严格口径开始执行的时间
     *
     * @return
     */
    private LocalDate getStrictStandardStartDate(String uid) {
        try {
            return LocalDate.parse(activityConfig.getStrictStandardStartTimeByUid(uid));

        } catch (Exception e) {
            log.error("getStrictStandardStartDate error", e);
        }
        return LocalDate.of(2023, 5, 1);
    }


}